package com.zhou.system.management.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.zhou.common.lib.exception.BizException;
import com.zhou.common.lib.model.CommonPage;
import com.zhou.common.lib.util.BeanUtil;
import com.zhou.common.lib.util.StringUtils;
import com.zhou.system.management.entity.SysDeptUser;
import com.zhou.system.management.entity.SysRole;
import com.zhou.system.management.entity.SysRoleRelation;
import com.zhou.system.management.enums.SysRoleRelationContentType;
import com.zhou.system.management.mapper.SysRoleMapper;
import com.zhou.system.management.model.ao.SysRoleAddAo;
import com.zhou.system.management.model.ao.SysRoleEnableAo;
import com.zhou.system.management.model.ao.SysRoleQueryAo;
import com.zhou.system.management.model.ao.SysRoleUpdateAo;
import com.zhou.system.management.model.vo.SysRoleVo;
import com.zhou.system.management.service.ISysRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.zhou.system.management.enums.ManageErrorCodeEnum.ROLE_EXSITS_USERS__ERROR;
import static com.zhou.system.management.enums.ManageErrorCodeEnum.ROLE_NOT_EXISTS_ERROR;

/**
 * <p>
 * 角色信息表 服务实现类
 * </p>
 *
 * @author zxf
 * @since 2023-05-18
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {

    @Autowired
    private SysDeptUserServiceImpl deptUserService;

    @Autowired
    private SysRoleRelationServiceImpl roleRelationService;

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void add(SysRoleAddAo ao) {
        SysRole sysRole = BeanUtil.copyObject(ao, SysRole.class);
        save(sysRole);
        List<SysRoleRelation> relations = Lists.newArrayList();
        if (CollectionUtil.isNotEmpty(ao.getDataPermissions())) {
            for (Long dataPermission : ao.getDataPermissions()) {
                SysRoleRelation dataPermRelation = new SysRoleRelation();
                dataPermRelation.setRoleId(sysRole.getRoleId());
                dataPermRelation.setContentId(dataPermission);
                dataPermRelation.setContentType(SysRoleRelationContentType.DEPT.getCode());
                relations.add(dataPermRelation);
            }
        }
        if (CollectionUtil.isNotEmpty(ao.getMenuIds())) {
            for (Long menuId : ao.getMenuIds()) {
                SysRoleRelation menuRelation = new SysRoleRelation();
                menuRelation.setRoleId(sysRole.getRoleId());
                menuRelation.setContentId(menuId);
                menuRelation.setContentType(SysRoleRelationContentType.MENU.getCode());
                relations.add(menuRelation);
            }
        }
        roleRelationService.saveBatch(relations);
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void update(SysRoleUpdateAo ao) {
        SysRole sysRole = BeanUtil.copyObject(ao, SysRole.class);
        updateById(sysRole);
        //删除老的关系
        LambdaQueryWrapper<SysRoleRelation> queryWrapper = Wrappers.<SysRoleRelation>lambdaQuery()
                .eq(SysRoleRelation::getRoleId, ao.getRoleId());
        roleRelationService.remove(queryWrapper);
        //新增数据权限和菜单权限
        List<SysRoleRelation> relations = Lists.newArrayList();
        if (CollectionUtil.isNotEmpty(ao.getDataPermissions())) {
            for (Long dataPermission : ao.getDataPermissions()) {
                SysRoleRelation dataPermRelation = new SysRoleRelation();
                dataPermRelation.setRoleId(sysRole.getRoleId());
                dataPermRelation.setContentId(dataPermission);
                dataPermRelation.setContentType(SysRoleRelationContentType.DEPT.getCode());
                relations.add(dataPermRelation);
            }
        }
        if (CollectionUtil.isNotEmpty(ao.getMenuIds())) {
            for (Long menuId : ao.getMenuIds()) {
                SysRoleRelation menuRelation = new SysRoleRelation();
                menuRelation.setRoleId(sysRole.getRoleId());
                menuRelation.setContentId(menuId);
                menuRelation.setContentType(SysRoleRelationContentType.MENU.getCode());
                relations.add(menuRelation);
            }
        }
        roleRelationService.saveBatch(relations);

    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void delete(Long roleId) {
        SysRole role = getById(roleId);
        if (role == null) {
            throw new BizException(ROLE_NOT_EXISTS_ERROR);
        }
        LambdaQueryWrapper<SysDeptUser> queryWrapper = Wrappers.<SysDeptUser>lambdaQuery()
                .eq(SysDeptUser::getPostId, roleId);
        int count = deptUserService.count(queryWrapper);
        if (count > 0) {
            throw new BizException(ROLE_EXSITS_USERS__ERROR);
        }
        removeById(roleId);
        //删除老的关系
        LambdaQueryWrapper<SysRoleRelation> relationQueryWrapper = Wrappers.<SysRoleRelation>lambdaQuery()
                .eq(SysRoleRelation::getRoleId, roleId);
        roleRelationService.remove(relationQueryWrapper);
    }

    @Override
    public CommonPage<SysRole> query(SysRoleQueryAo queryAo) {
        IPage<SysRole> iPage = queryAo.toPage();
        LambdaQueryWrapper<SysRole> queryWrapper = Wrappers.<SysRole>lambdaQuery()
                .like(StringUtils.isNotEmpty(queryAo.getRoleName()), SysRole::getRoleName, queryAo.getRoleName())
                .like(StringUtils.isNotEmpty(queryAo.getRoleKey()), SysRole::getRoleKey, queryAo.getRoleKey());
        page(iPage, queryWrapper);
        return CommonPage.fromMybatisPage(iPage);
    }

    @Override
    public void enableRole(SysRoleEnableAo ao) {
        SysRole sysRole = new SysRole();
        sysRole.setRoleId(ao.getRoleId());
        sysRole.setStatus(ao.getStatus());
        updateById(sysRole);
    }

    @Override
    public SysRoleVo queryOne(Long roleId) {
        SysRole role = getById(roleId);
        if (role == null) {
            throw new BizException(ROLE_NOT_EXISTS_ERROR);
        }
        SysRoleVo result = BeanUtil.copyObject(role, SysRoleVo.class);
        LambdaQueryWrapper<SysRoleRelation> relationQueryWrapper = Wrappers.<SysRoleRelation>lambdaQuery()
                .eq(SysRoleRelation::getRoleId, roleId);
        List<SysRoleRelation> list = roleRelationService.list(relationQueryWrapper);
        Map<Integer, List<SysRoleRelation>> relationMap =
                list.stream().collect(Collectors.groupingBy(SysRoleRelation::getContentType));
        List<SysRoleRelation> menuRelations = relationMap.get(SysRoleRelationContentType.MENU.getCode());
        List<SysRoleRelation> dataPermRelations = relationMap.get(SysRoleRelationContentType.DEPT.getCode());
        if (menuRelations != null && menuRelations.size() > 0) {
            List<Long> menuIds = menuRelations.stream().map(t -> t.getContentId()).collect(Collectors.toList());
            result.setMenuIds(menuIds);
        }
        if (dataPermRelations != null && dataPermRelations.size() > 0) {
            List<Long> permIds = dataPermRelations.stream().map(t -> t.getContentId()).collect(Collectors.toList());
            result.setDataPermissions(permIds);
        }
        return result;
    }
}
